home *** CD-ROM | disk | FTP | other *** search
/ Belgian Amiga Club - ADF Collection / BS1 part 34.zip / BS1 part 34 / FredFish PD 316.adf / Vectors / V1.1 / src / ciatimer.c < prev    next >
C/C++ Source or Header  |  1990-02-06  |  4KB  |  161 lines

  1.  
  2. #include <exec/types.h>
  3. #include <exec/tasks.h>
  4. #include <exec/interrupts.h>
  5. #include <hardware/cia.h>
  6. #include <hardware/custom.h>
  7. #include <hardware/intbits.h>
  8. #include <resources/cia.h>
  9. #include <stdio.h>
  10.  
  11. static struct CIA *ciaa = (struct CIA *) 0x00BFE001L;
  12. static struct CIA *ciab = (struct CIA *) 0x00BFD000L;
  13.  
  14. long CIA_Seconds = 0;
  15. long CIA_Microseconds = 0;
  16.  
  17. /* timeslice is 46911 intervals.  Each interval is 1.397 microseconds,
  18.  * this should correspond to a timing interval of 65536 microseconds */
  19. #define CIA_TIME_SLICE ((unsigned short) 46911)
  20.  
  21. static struct Interrupt
  22.    CIATimerInterrupt,
  23.    *OldCIAInterrupt = (struct Interrupt *)-1;
  24.  
  25. static struct Library *CIAResource = NULL;
  26.  
  27. #define ciatlo ciaa->ciatalo
  28. #define ciathi ciaa->ciatahi
  29. #define ciacr  ciaa->ciacra
  30. #define CIAINTBIT CIAICRB_TA
  31. #define CLEAR 0
  32.  
  33.  
  34. /* this is the actual interrupt routine.  since +p 32-bit model is used,
  35.  * no special dinking around is necessary to get a C routine to run as
  36.  * an interrupt.
  37.  */
  38. VOID CIAInterrupt()
  39. {
  40.     /* increment saved microseconds by number generated between CIA
  41.      * interrupts, and if we passed a million, increment seconds */
  42.     CIA_Microseconds += 65536;
  43.     if (CIA_Microseconds > 1000000)
  44.     {
  45.         CIA_Seconds++;
  46.         CIA_Microseconds -= 1000000;
  47.     }
  48. }
  49.  
  50. /* start the timer, clear pending interrupts, and enable timer A
  51.  * Interrupts */
  52. void StartCIATimer()
  53. {
  54.     ciacr &= ~(CIACRAF_RUNMODE);    /* set it to reload on overflow */
  55.     ciacr |= (CIACRAF_LOAD | CIAICRF_TA);
  56.     SetICR(CIAResource,CLEAR|CIAICRF_TA);
  57.     AbleICR(CIAResource, CIAICRF_SETCLR | CIAICRF_TA);
  58. }
  59.  
  60. void StopCIATimer()
  61. {
  62.     AbleICR(CIAResource, CLEAR | CIAICRF_TA);
  63.     ciacr &= ~CIACRAF_START;
  64. }
  65.  
  66. /* set period between timer increments */
  67. void SetCIATimer(micros)
  68. unsigned short micros;
  69. {
  70.     ciatlo = micros & 0xff;
  71.     ciathi = micros >> 8;
  72. }
  73.  
  74. /* stop the timer and remove its interrupt vector */
  75. void EndCIATimer()
  76. {
  77.     if (OldCIAInterrupt == NULL)
  78.     {
  79.         StopCIATimer();
  80.         RemICRVector(CIAResource, CIAINTBIT, &CIATimerInterrupt);
  81.     }
  82. }
  83.  
  84. BOOL BeginCIATimer()
  85. {
  86.     extern struct Interrupt *AddICRVector();
  87.  
  88.     /* Open the CIA resource */
  89.     if ((CIAResource = (struct Library *)OpenResource(CIAANAME)) == NULL)
  90.        return(FALSE);
  91.  
  92.     CIATimerInterrupt.is_Node.ln_Type = NT_INTERRUPT;
  93.     CIATimerInterrupt.is_Node.ln_Pri = 127;
  94.     CIATimerInterrupt.is_Code = CIAInterrupt;
  95.  
  96.     /* install interrupt */
  97.     if ((OldCIAInterrupt = AddICRVector(CIAResource,CIAINTBIT,&CIATimerInterrupt)) != NULL)
  98.        {
  99.        EndCIATimer();
  100.        return(FALSE);
  101.        }
  102.  
  103.     SetCIATimer(CIA_TIME_SLICE);
  104.  
  105.     StartCIATimer();
  106.     return(TRUE);
  107. }
  108.  
  109. /* return the elapsed real time in seconds and microseconds since the
  110.  * cia timer interrupt handler was installed.
  111.  *
  112.  * ElapsedTime(&secs,µsecs);
  113.  *
  114.  * with the chosen timeslice interval, every timer interrupt represents
  115.  * 65536 microseconds, so the count of interrupts received can be shifted
  116.  * and or'ed in.  The thing that needs scaling is the timer count we
  117.  * read from the hardware registers.  It's range of 0 - 46911 1.397
  118.  * microsecond ticks must be changed to a range of 0 - 65535 1.0
  119.  * microsecond ticks, which is done below
  120.  *
  121.  * note the code should really read the lo count register again after
  122.  * reading the high one and comparing them to be sure it didn't wrap
  123.  * in between reads
  124.  *
  125.  * interrupts are off during this to reduce the possibility of a problem
  126.  * with the counter interrupt coming between the cia reads and the big tick
  127.  * read, and because it's short it's no biggie, but again it should
  128.  * really do more
  129.  */
  130. void ElapsedTime(sec_ptr,usec_ptr)
  131. int *sec_ptr,*usec_ptr;
  132. {
  133.     register long seconds, microseconds;
  134.     register long ciahi, cialo;
  135.  
  136.     Disable();
  137.     ciahi = ciathi;
  138.     cialo = ciatlo;
  139.     seconds = CIA_Seconds;
  140.     microseconds = CIA_Microseconds;
  141.     Enable();
  142.     /* total microseconds is CIA_BigTicks * 65536 + timerval * 1.397 */
  143.     /* to multiply the timer ticks * 1.397, you can multiply by 1430
  144.      * and divide by 1024 (or shift right by 10, get it?)
  145.      */
  146.     ciahi = CIA_TIME_SLICE - ((ciahi << 8) + cialo);
  147.     ciahi = ((ciahi * 1430) >> 10) & 0xffff;
  148.  
  149.     microseconds += ciahi;
  150.     if (microseconds > 1000000)
  151.     {
  152.         microseconds -= 1000000;
  153.         seconds++;
  154.     }
  155.  
  156.     *sec_ptr = seconds;
  157.     *usec_ptr = microseconds;
  158.     return;
  159. }
  160.  
  161.